package cn.rgb.orm.impl;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.rgb.common.BeanUtilsx;
import cn.rgb.orm.config.SqlMapping;
import cn.rgb.orm.config.SqlOperateMapping;

public class StatementArgsMapper {

	protected static final String PLACEHOLDER_REGEX = "#[\\w]+#";
	protected static final String STANDARD_PLACEHOLDER = "?";
	
	@SuppressWarnings("unchecked")
	public PreparedStatement setStatementArgs(String operSqlId, Connection conn, Object param, SqlMapping sqlMapping) throws SQLException {
		SqlOperateMapping sqlOperMapping = sqlMapping.getSqlOprate(operSqlId);
		String sql = sqlOperMapping.getSql();
		List<String> placeholders = parseSql(sql);
		sql = sql.replaceAll(PLACEHOLDER_REGEX, STANDARD_PLACEHOLDER);
		PreparedStatement ps = conn.prepareStatement(sql);
		if(!placeholders.isEmpty()) {			
			if(param == null) {
				
			} else if(param instanceof java.util.Map) {
				dealMap(ps, placeholders, (Map<String, Object>) param);
			} else {
				dealBean(ps, placeholders, param);
			}
		}
		return ps;
	}
	
	public void dealBean(PreparedStatement ps, List<String> placeholders, Object param) throws SQLException {
		List<Object> values = BeanUtilsx.getFieldValues(placeholders, param);
		for(int index = 0, size = values.size(); index < size; index++) {
			dealCommonArgs(ps, index + 1, null, values.get(index));
		}
	}
	
	public void dealMap(PreparedStatement ps, List<String> placeholders, Map<String, Object> param) throws SQLException {
		Map<String, Object> paramMap = (Map<String, Object>) param;
		for(int index = 0, size = placeholders.size(); index < size; index++) {
			dealCommonArgs(ps, index + 1, null, paramMap.get(paramMap.get(index)));
		}
	}
	
	public void dealCommonArgs(PreparedStatement ps, int index, String type, Object param) throws SQLException {
		if(param == null) {
			ps.setString(index, "null");
			return;
		}
		Class<?> clazz = param.getClass();
		if(Byte.class.equals(clazz)) {
			ps.setByte(index, (Byte) param);
		} else if(Boolean.class.equals(clazz)) {
			ps.setBoolean(index, (Boolean) param);
		} else if(Integer.class.equals(clazz)) {
			ps.setInt(index, (Integer) param);
		} else if(Long.class.equals(clazz)) {
			ps.setLong(index, (Long) param);
		} else if(Float.class.equals(clazz)) {
			ps.setFloat(index, (Float) param);
		} else if(Double.class.equals(clazz)) {
			ps.setDouble(index, (Double) param);
		} else if(String.class.equals(clazz)) {
			ps.setString(index, (String) param);
		} else if(Date.class.equals(clazz)) {
			ps.setDate(index, (Date) param);
		} else if(java.util.Date.class.equals(clazz)) {
			ps.setDate(index, new Date(1000));
		}
	}
	
	public List<String> parseSql(String sql) {
		List<String> placeholders = new ArrayList<String>();
		Pattern pattern = Pattern.compile(PLACEHOLDER_REGEX);
		Matcher matcher = pattern.matcher(sql);
		while(matcher.find()) {
			placeholders.add(matcher.group().replaceAll("#", ""));
		}
		return placeholders;
	}
	
	public static void main(String argv[]) {
		String sql = "update ACCOUNT set "
				+ "ACC_FIRST_NAME = #firstName#, "
				+ "ACC_LAST_NAME = #lastName#, "
				+ "ACC_EMAIL = #emailAddress# "
				+ "where "
				+ "ACC_ID = #id#";
		Pattern p = Pattern.compile("#[\\w]+#");
		Matcher m = p.matcher(sql);
		while(m.find()) {
			System.out.println(m.group());
		}
	}
}
